<template>
  <div class="requirements-workspace">
    <header class="workspace-header">
      <div class="header-left">
        <div class="title-block">
          <h2>需求工作台</h2>
          <p class="subtitle">在一个位置管理、筛选、分析并协同处理所有需求</p>
        </div>
      </div>
      <div class="header-right">
        <div class="project-selector-wrapper">
          <label class="project-label">所属项目：</label>
          <el-select
            v-model="selectedProjectId"
            :placeholder="requirementsStore.projects.length > 0 ? '请选择项目' : '暂无项目'"
            filterable
            class="project-selector"
            :clearable="false"
            :disabled="requirementsStore.projects.length === 0"
            @change="handleProjectChange"
          >
            <el-option
              v-for="project in requirementsStore.projects"
              :key="project.id"
              :label="project.name"
              :value="project.id"
            />
          </el-select>
        </div>
        <el-button 
          text
          class="refresh-button"
          @click="handleRefresh"
        >
          <el-icon><Refresh /></el-icon>
          刷新
        </el-button>
        <el-button 
          v-if="canCreate"
          type="primary" 
          class="create-button"
          @click="handleOpenCreate"
        >
          <el-icon><Plus /></el-icon>
          新建需求
        </el-button>
        <el-radio-group
          v-model="viewModeProxy"
          class="view-switcher"
        >
          <el-radio-button
            v-for="option in viewOptions"
            :key="option.value"
            :label="option.value"
          >
            {{ option.label }}
            </el-radio-button>
          </el-radio-group>
      </div>
    </header>

    <div class="workspace-main">
      <aside :class="['filter-panel', { 'is-collapsed': filterCollapsed }]">
        <header class="filter-header">
          <h3>筛选条件</h3>
          <el-button text size="small" class="collapse-btn" @click="toggleFilterCollapsed">
            <el-icon><DArrowLeft v-if="!filterCollapsed" /><DArrowRight v-else /></el-icon>
            </el-button>
        </header>
        <div class="filter-body" v-show="!filterCollapsed">
          <RequirementFilterBar
            :filters="requirementsStore.filters"
            :projects="requirementsStore.projects"
            :users="requirementsStore.users"
            :status-options="requirementsStore.statusOptions"
            :priority-options="requirementsStore.priorityOptions"
              :type-options="requirementsStore.typeOptions as any"
              :source-options="requirementsStore.sourceOptions as any"
            :current-user-id="currentUserId"
            @apply="handleFilterApply"
            @reset="handleFilterReset"
          />
        </div>
      </aside>

      <section class="workspace-content">
        <main class="workspace-body">
          <!-- 初始加载状态 -->
          <PageLoading 
            v-if="initialLoading"
            :title="isRefreshing ? '正在刷新数据' : '正在加载需求数据'"
            :subtitle="isRefreshing ? '请稍候，正在更新数据...' : '请稍候，正在为您准备数据...'"
          />
          <!-- 内容区域 -->
          <transition v-else name="fade-slide" mode="out-in">
            <component
              :is="activeViewComponent"
              :key="`${requirementsStore.viewMode}-${statusOptionsKey}`"
              :requirements="requirementsStore.requirements"
              :loading="requirementsStore.loading"
              :pagination="requirementsStore.pagination"
              :status-options="requirementsStore.viewMode === 'kanban' ? requirementsStore.allStatusOptions : requirementsStore.statusOptions"
              :priority-options="priorityOptionsForList"
              :type-options="typeOptionsForList"
              :source-options="sourceOptionsForList"
              :users="userOptionsForList"
              :selected-ids="requirementsStore.selectedIds"
              :batch-loading="batchLoading"
              :status-options-for-batch="requirementsStore.statusOptions"
              :priority-options-for-batch="requirementsStore.priorityOptions"
              :users-for-batch="requirementsStore.users"
              @page-change="handlePageChange"
              @page-size-change="handlePageSizeChange"
              @select-change="handleSelectionChange"
              @sort-change="handleSortChange"
              @open-detail="handleOpenDetail"
              @delete="handleDelete"
              @refresh="handleRefresh"
              @update-status="handleUpdateStatus"
              @update-priority="handleUpdatePriority"
              @update-type="handleUpdateType"
              @update-source="handleUpdateSource"
              @update-assignee="handleUpdateAssignee"
              @update-reporter="handleUpdateReporter"
              @update-start-date="handleUpdateStartDate"
              @update-due-date="handleUpdateDueDate"
              @update-estimated-effort="handleUpdateEstimatedEffort"
              @update-actual-effort="handleUpdateActualEffort"
              @update-progress="handleUpdateProgress"
              @split-task="handleSplitTask"
              @create-requirement="handleCreateRequirementFromKanban"
              @batch-update-status="handleBatchUpdateStatus"
              @batch-update-priority="handleBatchUpdatePriority"
              @batch-update-type="handleBatchUpdateType"
              @batch-update-source="handleBatchUpdateSource"
              @batch-assign="handleBatchAssign"
              @batch-update-reporter="handleBatchUpdateReporter"
              @batch-update-project-version="handleBatchUpdateProjectAndVersion"
              @batch-delete="handleBatchDelete"
              @batch-clear="handleClearSelection"
              @download-template="handleDownloadTemplate"
              @import="handleImportFile"
              @export="handleExportRequirements"
              @search="handleListSearch"
            />
          </transition>
        </main>
      </section>
      </div>

    <RequirementDetail
      v-if="requirementsStore.activeRequirementId && requirementsStore.activeRequirement"
      :visible="requirementsStore.detailVisible && !!requirementsStore.activeRequirementId && !!requirementsStore.activeRequirement"
      :requirement="requirementsStore.activeRequirement"
      :projects="requirementsStore.projects"
      :users="requirementsStore.users"
      :status-options="requirementsStore.statusOptions"
      :priority-options="requirementsStore.priorityOptions"
      :common-tags="requirementsStore.tagOptions"
      :current-user-id="currentUserId"
      :version-options="versionOptions"
      @update:visible="handleDetailVisibleChange"
      @updated="handleRequirementUpdated"
      @comment-added="handleRequirementComment"
      @request-version-options="handleRequestVersionOptions"
      @create-child="handleCreateChild"
      @view-child="handleViewChild"
    />
    <CreateRequirement
      :visible="requirementsStore.detailVisible && !requirementsStore.activeRequirementId"
      :projects="requirementsStore.projects"
      :users="requirementsStore.users"
      :status-options="requirementsStore.statusOptions"
      :priority-options="requirementsStore.priorityOptions"
      :common-tags="requirementsStore.tagOptions"
      :current-user-id="currentUserId"
      :default-project-id="requirementsStore.editorDefaultProjectId || ''"
      :default-parent-id="defaultParentId"
      :default-parent-name="defaultParentName"
      :default-status="defaultStatus"
      :version-options="versionOptions"
      @update:visible="handleCreateVisibleChange"
      @created="handleRequirementCreated"
      @request-version-options="handleRequestVersionOptions"
    />

    <!-- 任务创建对话框（用于任务拆分） -->
    <TaskCreateDialog
      v-model="taskSplitDialogVisible"
      :project-id="taskSplitRequirement?.project_id || ''"
      :default-requirement-id="taskSplitRequirement?.id || ''"
      @success="handleTaskCreated"
    />

    <!-- 批量更新弹窗 -->
    <RequirementBatchUpdateDialog
      v-model="batchUpdateDialogVisible"
      :title="batchUpdateDialogTitle"
      :placeholder="batchUpdateDialogPlaceholder"
      :selected-count="requirementsStore.selectedIds.length"
      :type="batchUpdateDialogType"
      :options="batchUpdateDialogOptions"
      :users="batchUpdateDialogUsers"
      :projects="batchUpdateDialogProjects"
      :versions="batchUpdateDialogVersions"
      :default-value="batchUpdateDialogDefaultValue"
      :default-project-id="batchUpdateDialogDefaultProjectId"
      :default-version-id="batchUpdateDialogDefaultVersionId"
      :loading="batchUpdateLoading"
      :on-load-versions="batchUpdateDialogLoadVersions"
      @confirm="handleBatchUpdateConfirm"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, DArrowLeft, DArrowRight, Refresh } from '@element-plus/icons-vue'

import RequirementFilterBar from './components/RequirementFilterBar.vue'
import RequirementDetail from './components/RequirementDetail.vue'
import CreateRequirement from './components/CreateRequirement.vue'
import RequirementListView from './views/RequirementListView.vue'
import RequirementKanbanView from './views/RequirementKanbanView.vue'
import TaskCreateDialog from '@/components/task/TaskCreateDialog.vue'
import RequirementBatchUpdateDialog from './components/RequirementBatchUpdateDialog.vue'
import PageLoading from '@/components/ui/PageLoading.vue'

import { useRequirementsStore, type RequirementFilters } from '@/stores/requirements'
import { useStateStore } from '@/stores/state'
import { ModuleType } from '@/types/state'
import {
  batchDeleteRequirements,
  batchUpdateRequirements,
  deleteRequirement,
  updateRequirement,
  type RequirementBulkUpdate,
  type RequirementUpdate,
  downloadRequirementTemplate,
  importRequirements,
  exportRequirements
} from '@/api/requirements'
import { versionAPI, RelationType } from '@/api/version'
import { useUserStore } from '@/stores/user'
import { ResponseParser } from '@/utils/responseParser'

const requirementsStore = useRequirementsStore()
const userStore = useUserStore()
const stateStore = useStateStore()

const batchLoading = ref(false)
const batchUpdateLoading = ref(false)
const filterCollapsed = ref(false)
const initialLoading = ref(true)
const isRefreshing = ref(false)
const versionOptions = ref<Array<{
  id: string
  name: string
  version_number?: string
  status?: string
  project_id?: string
}>>([])
const defaultParentId = ref<string | null>(null)
const defaultParentName = ref<string>('')
const defaultStatus = ref<string>('')

// 批量更新弹窗相关状态
const batchUpdateDialogVisible = ref(false)
const batchUpdateDialogTitle = ref('')
const batchUpdateDialogPlaceholder = ref('请选择')
const batchUpdateDialogType = ref<'select' | 'user' | 'project-version'>('select')
const batchUpdateDialogOptions = ref<Array<{ value: string; label: string }>>([])
const batchUpdateDialogUsers = ref<Array<any>>([])
const batchUpdateDialogProjects = ref<Array<{ value: string; label: string }>>([])
const batchUpdateDialogVersions = ref<Array<{ value: string; label: string }>>([])
const batchUpdateDialogDefaultValue = ref<string | undefined>(undefined)
const batchUpdateDialogDefaultProjectId = ref<string | undefined>(undefined)
const batchUpdateDialogDefaultVersionId = ref<string | undefined>(undefined)
const batchUpdateDialogCallback = ref<((value: string | { projectId: string; versionId?: string }) => Promise<void>) | null>(null)
const batchUpdateDialogLoadVersions = ref<((projectId: string) => Promise<Array<{ value: string; label: string }>>) | undefined>(undefined)

// 用于强制更新看板视图的 key，当状态选项变化时更新
const statusOptionsKey = computed(() => {
  return requirementsStore.statusOptions.map(opt => `${opt.value}:${opt.label}`).join(',')
})

const currentUserId = computed(() => userStore.userInfo?.id ?? '')
const canCreate = computed(() => userStore.hasPermission?.('REQUIREMENT_CREATE') ?? false)

const viewOptions = [
  { label: '列表', value: 'list', icon: 'List' },
  { label: '看板', value: 'kanban', icon: 'Grid' }
]

const viewComponentMap: Record<'list' | 'kanban', any> = {
  list: RequirementListView,
  kanban: RequirementKanbanView
}

const activeViewComponent = computed(() => viewComponentMap[requirementsStore.viewMode] || RequirementListView)

// 格式化优先级选项供列表视图使用
const priorityOptionsForList = computed(() => {
  // priorityOptions 是 StateOption[] 格式，包含 value 和 label
  return (requirementsStore.priorityOptions as any[]).map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

// 格式化类型选项供列表视图使用
const typeOptionsForList = computed(() => {
  return (requirementsStore.typeOptions as any[]).map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

// 格式化来源选项供列表视图使用
const sourceOptionsForList = computed(() => {
  return (requirementsStore.sourceOptions as any[]).map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

// 格式化用户选项供列表视图使用
const userOptionsForList = computed(() => {
  return requirementsStore.users.map(user => ({
    id: user.id,
    name: user.name || user.username || ''
  }))
})

// 选中的项目ID（从筛选条件中获取）
const selectedProjectId = computed({
  get: () => requirementsStore.filters.project_id || '',
  set: (value: string) => {
    requirementsStore.filters.project_id = value || undefined
  }
})

// 项目变化处理
const handleProjectChange = async (projectId: string) => {
  if (projectId) {
    // 刷新用户列表（项目成员）
    await requirementsStore.refreshUsers()
    // 刷新需求列表
    await requirementsStore.fetchRequirements()
  } else {
    // 如果清空项目，清空用户列表和需求列表
    requirementsStore.users = []
    requirementsStore.requirements = []
  }
}

onMounted(async () => {
  try {
    // 先加载基础数据
    await requirementsStore.bootstrapOptions()
    
    // 如果没有选择项目，默认选择第一个项目
    if (!requirementsStore.filters.project_id && requirementsStore.projects.length > 0) {
      const firstProject = requirementsStore.projects[0]
      requirementsStore.filters.project_id = firstProject.id
      // 加载项目成员
      await requirementsStore.refreshUsers()
    }
    
    // 加载需求列表
    await requirementsStore.fetchRequirements()
  } catch (error) {
    console.error('加载需求数据失败:', error)
    ElMessage.error('加载数据失败，请稍后重试')
  } finally {
    // 延迟一点显示内容，让加载动画更自然
    setTimeout(() => {
      initialLoading.value = false
    }, 300)
  }
})

// 监听状态 store 中需求模块的状态变化，自动刷新状态列表
watch(
  () => stateStore.getStatesByModule(ModuleType.REQUIREMENT),
  async (newStates, oldStates) => {
    // 如果状态列表发生变化（长度变化或状态被启用/禁用），重新加载状态
    if (!oldStates || newStates.length !== oldStates.length) {
      // 状态数量变化，清除缓存并重新加载
      stateStore.clearModuleCache(ModuleType.REQUIREMENT)
      await requirementsStore.bootstrapOptions()
      return
    }
    
    // 检查是否有状态的 is_enabled 或 is_visible 发生变化
    const hasStateChanged = newStates.some((newState) => {
      const oldState = oldStates.find(s => s.id === newState.id)
      if (!oldState) return true
      return (
        oldState.is_enabled !== newState.is_enabled ||
        oldState.is_visible !== newState.is_visible ||
        oldState.code !== newState.code ||
        oldState.name !== newState.name ||
        oldState.color !== newState.color
      )
    })
    
    if (hasStateChanged) {
      // 状态属性变化，清除缓存并重新加载状态
      stateStore.clearModuleCache(ModuleType.REQUIREMENT)
      await requirementsStore.bootstrapOptions()
    }
  },
  { deep: true, immediate: false }
)

const handleViewChange = (mode: string | number | boolean) => {
  if (typeof mode === 'string' && ['list', 'kanban'].includes(mode)) {
    requirementsStore.setViewMode(mode as 'list' | 'kanban')
  }
}

const viewModeProxy = computed({
  get: () => requirementsStore.viewMode,
  set: value => {
    handleViewChange(value)
  }
})

const handleOpenCreate = () => {
  defaultStatus.value = ''
  requirementsStore.openCreateDrawer()
}

const handleCreateRequirementFromKanban = (status: string) => {
  defaultStatus.value = status
  requirementsStore.openCreateDrawer()
}

const handleFilterApply = async (filters: Partial<RequirementFilters>) => {
  await requirementsStore.applyFilters(filters)
}

const handleFilterReset = async () => {
  await requirementsStore.resetFilters()
}

// 处理列表搜索
const handleListSearch = async (keyword: string) => {
  await requirementsStore.applyFilters({ search: keyword })
}

const handleSelectionChange = (ids: string[]) => {
  // 获取当前页面的所有需求ID
  const currentPageIds = requirementsStore.requirements.map(req => req.id)
  requirementsStore.toggleSelection(ids, currentPageIds)
}

const handlePageChange = async (page: number) => {
  await requirementsStore.setPage(page)
}

const handlePageSizeChange = async (size: number) => {
  await requirementsStore.setPageSize(size)
}

// 处理排序变化
const handleSortChange = ({ prop, order }: { prop: string; order: 'ascending' | 'descending' | null }) => {
  if (!prop || !order) {
    // 清除排序
    requirementsStore.setSort(undefined, undefined)
  } else {
    // 转换排序顺序：ascending -> asc, descending -> desc
    const sortOrder = order === 'ascending' ? 'asc' : 'desc'
    requirementsStore.setSort(prop, sortOrder)
  }
}

const handleOpenDetail = async (id: string) => {
  // 如果已经打开了同一个需求，直接返回
  if (requirementsStore.activeRequirementId === id && requirementsStore.detailVisible) {
    return
  }
  await requirementsStore.openDetailPanel(id)
}

const handleDelete = async (id: string) => {
  try {
    await ElMessageBox.confirm(
      '确定要删除该需求吗？删除后无法恢复。',
      '确认删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
    
    const response = await deleteRequirement(id)
    if (response.success) {
      ElMessage.success('删除成功')
      // 如果删除的是当前查看的需求，关闭详情面板
      if (requirementsStore.activeRequirementId === id) {
        requirementsStore.closeDetailPanel()
      }
      // 刷新需求列表
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '删除失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('删除需求失败:', error)
      const errorMessage = ResponseParser.extractMessage(error) || '删除需求失败'
      ElMessage.error(errorMessage)
    }
  }
}

const handleRefresh = async () => {
  try {
    // 标记为刷新状态并显示加载状态
    isRefreshing.value = true
    initialLoading.value = true
    
    // 同时刷新所有数据
    await Promise.all([
      // 刷新选项数据（强制刷新）
      requirementsStore.bootstrapOptions(true),
      // 刷新需求列表
      requirementsStore.fetchRequirements(),
      // 如果当前打开了详情面板，也刷新详情数据
      requirementsStore.activeRequirementId 
        ? requirementsStore.fetchRequirementDetail(requirementsStore.activeRequirementId)
        : Promise.resolve()
    ])
    
    ElMessage.success('刷新成功')
  } catch (error) {
    console.error('刷新失败:', error)
    ElMessage.error('刷新失败，请稍后重试')
  } finally {
    // 延迟一点隐藏加载状态，让动画更自然
    setTimeout(() => {
      initialLoading.value = false
      isRefreshing.value = false
    }, 300)
  }
}

// 任务拆分相关状态
const taskSplitDialogVisible = ref(false)
const taskSplitRequirement = ref<{ id: string; project_id: string; title: string } | null>(null)

// 处理任务拆分
const handleSplitTask = (requirement: any) => {
  if (!requirement || !requirement.id) {
    ElMessage.warning('无法识别需求信息')
    return
  }
  
  taskSplitRequirement.value = {
    id: requirement.id,
    project_id: requirement.project_id || '',
    title: requirement.title || ''
  }
  taskSplitDialogVisible.value = true
}

// 任务创建成功后的处理
const handleTaskCreated = async () => {
  const requirementId = taskSplitRequirement.value?.id
  taskSplitRequirement.value = null
  taskSplitDialogVisible.value = false
  
  // 刷新需求列表
  await requirementsStore.fetchRequirements()
  
  // 如果当前打开了需求详情且是刚拆分任务的需求，刷新需求详情（包括关联任务列表）
  if (requirementId && requirementsStore.activeRequirementId === requirementId) {
    await requirementsStore.fetchRequirementDetail(requirementId)
  }
}

const handleUpdateStatus = async (payload: { id: string; status: string }) => {
  // 如果ID或状态为空，可能是错误情况，直接返回
  if (!payload.id || !payload.status) {
    // 如果ID为空但状态也为空，可能是恢复操作，重新加载数据
    if (!payload.id && !payload.status) {
      await requirementsStore.fetchRequirements()
    }
    return
  }
  
  try {
    const success = await requirementsStore.updateRequirementStatus(payload.id, payload.status)
    if (!success) {
      ElMessage.error('状态更新失败')
      // 如果更新失败，重新获取数据以恢复正确状态
      // vuedraggable 会在数据刷新后自动恢复到正确位置
      await requirementsStore.fetchRequirements()
      return
    }
    
    // 更新成功后，需要重新获取数据以确保数据一致性
    // 特别是在看板视图中，确保需求在正确的列中，并且所有字段都是最新的
    await requirementsStore.fetchRequirements()
    
    // 如果当前有活动的需求详情，也刷新它
    const requirementId = payload.id
    if (requirementId && requirementsStore.activeRequirementId === requirementId) {
      await requirementsStore.fetchRequirementDetail(requirementId)
    }
  } catch (error) {
    console.error('更新状态失败:', error)
    ElMessage.error('状态更新失败，请稍后重试')
    // 发生错误时重新获取数据以恢复正确状态
    await requirementsStore.fetchRequirements()
  }
}

const handleUpdatePriority = async (id: string, priority: string) => {
  if (!id || !priority) return
  try {
    const response = await updateRequirement(id, { priority: priority as any })
    if (response.success) {
      ElMessage.success('优先级更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '优先级更新失败')
    }
  } catch (error) {
    console.error('更新优先级失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新优先级失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateAssignee = async (id: string, assigneeId: string | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { assignee_id: assigneeId })
    if (response.success) {
      ElMessage.success('负责人更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '负责人更新失败')
    }
  } catch (error) {
    console.error('更新负责人失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新负责人失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateReporter = async (id: string, reporterId: string | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { reporter_id: reporterId ?? undefined })
    if (response.success) {
      ElMessage.success('报告人更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '报告人更新失败')
    }
  } catch (error) {
    console.error('更新报告人失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新报告人失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateType = async (id: string, type: string) => {
  if (!id || !type) return
  try {
    const response = await updateRequirement(id, { requirement_type: type as any })
    if (response.success) {
      ElMessage.success('类型更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '类型更新失败')
    }
  } catch (error) {
    console.error('更新类型失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新类型失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateSource = async (id: string, source: string) => {
  if (!id || !source) return
  try {
    const response = await updateRequirement(id, { source: source as any })
    if (response.success) {
      ElMessage.success('来源更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '来源更新失败')
    }
  } catch (error) {
    console.error('更新来源失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新来源失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateStartDate = async (id: string, startDate: string | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { start_date: startDate || null })
    if (response.success) {
      ElMessage.success('开始日期更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '开始日期更新失败')
    }
  } catch (error) {
    console.error('更新开始日期失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新开始日期失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateDueDate = async (id: string, dueDate: string | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { due_date: dueDate || null })
    if (response.success) {
      ElMessage.success('截止日期更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '截止日期更新失败')
    }
  } catch (error) {
    console.error('更新截止日期失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新截止日期失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateEstimatedEffort = async (id: string, effort: number | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { estimated_effort: effort ?? undefined })
    if (response.success) {
      ElMessage.success('预估工时更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '预估工时更新失败')
    }
  } catch (error) {
    console.error('更新预估工时失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新预估工时失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateActualEffort = async (id: string, effort: number | null) => {
  if (!id) return
  try {
    const response = await updateRequirement(id, { actual_effort: effort ?? undefined })
    if (response.success) {
      ElMessage.success('实际工时更新成功')
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '实际工时更新失败')
    }
  } catch (error) {
    console.error('更新实际工时失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新实际工时失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateProgress = async (_id: string, _progress: number | null) => {
  // 注意：进度是根据状态自动计算的，不支持直接更新
  // 如果需要更新进度，应该通过更新状态来实现
  ElMessage.warning('进度是根据状态自动计算的，无法直接更新。如需更新进度，请更新需求状态。')
}

const handleDetailVisibleChange = (visible: boolean) => {
  requirementsStore.detailVisible = visible
  if (!visible) {
    requirementsStore.closeDetailPanel()
  } else {
    handleRequestVersionOptions()
  }
}

const handleCreateVisibleChange = (visible: boolean) => {
  requirementsStore.detailVisible = visible
  if (!visible) {
    requirementsStore.closeDetailPanel()
  } else {
    handleRequestVersionOptions()
  }
}

const handleRequirementCreated = (requirementId: string) => {
  requirementsStore.fetchRequirements()
  requirementsStore.closeDetailPanel()
  // 清除父需求信息和默认状态
  defaultParentId.value = null
  defaultParentName.value = ''
  defaultStatus.value = ''
  // 可以选择打开新创建的需求详情
  if (requirementId) {
    requirementsStore.openDetailPanel(requirementId)
  }
}

const handleCreateChild = (parentId: string) => {
  // 设置父需求ID和名称
  const parentRequirement = requirementsStore.activeRequirement
  if (parentRequirement) {
    defaultParentId.value = parentId
    defaultParentName.value = parentRequirement.title || ''
    // 关闭详情页，打开新建页面
    requirementsStore.closeDetailPanel()
    requirementsStore.openCreateDrawer(parentRequirement.project_id)
  }
}

const handleViewChild = async (childId: string) => {
  // 查看子需求（或父需求）
  await requirementsStore.openEditDrawer(childId)
}

const handleRequirementUpdated = async (id: string) => {
  // 刷新需求列表
  await requirementsStore.fetchRequirements()
  // 刷新需求详情（如果当前正在查看该需求）
  if (requirementsStore.activeRequirementId === id) {
    await requirementsStore.fetchRequirementDetail(id)
  }
}

const handleRequirementComment = () => {
  if (requirementsStore.activeRequirementId) {
    requirementsStore.fetchRequirementDetail(requirementsStore.activeRequirementId)
  }
}

const handleRequestVersionOptions = async () => {
  const projectId =
    requirementsStore.activeRequirement?.project_id || requirementsStore.editorDefaultProjectId || ''
  try {
    const response = await versionAPI.getVersions({ project_id: projectId, limit: 200 })
    if (response.success && response.data?.items) {
      versionOptions.value = response.data.items.map(item => ({
        id: item.id,
        name: item.name || item.version_number || `版本 ${item.id}`,
        version_number: item.version_number,
        status: item.status,
        project_id: item.project_id
      }))
    } else {
      versionOptions.value = []
    }
  } catch (error) {
    console.error('加载版本列表失败', error)
    versionOptions.value = []
  }
}

const toggleFilterCollapsed = () => {
  filterCollapsed.value = !filterCollapsed.value
}

// 下载导入模板
const handleDownloadTemplate = async () => {
  try {
    batchLoading.value = true
    
    const response = await downloadRequirementTemplate()
    
    // 处理文件下载
    const blob = new Blob([response.data], {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    
    // 从响应头获取文件名，或使用默认文件名
    const contentDisposition = response.headers['content-disposition'] || response.headers['Content-Disposition']
    let filename = `需求导入模板_${new Date().getTime()}.xlsx`
    if (contentDisposition) {
      // 优先匹配 RFC 5987 格式：filename*=UTF-8''<encoded>
      const rfc5987Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i)
      if (rfc5987Match && rfc5987Match[1]) {
        try {
          filename = decodeURIComponent(rfc5987Match[1])
        } catch {
          filename = rfc5987Match[1]
        }
      } else {
        // 回退到标准格式：filename="..." 或 filename=...
        const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
        if (filenameMatch && filenameMatch[1]) {
          filename = filenameMatch[1].replace(/['"]/g, '')
          try {
            filename = decodeURIComponent(filename)
          } catch {
            // 如果解码失败，使用原始文件名
          }
        }
      }
    }
    
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    
    ElMessage.success('模板下载成功')
  } catch (error) {
    console.error('下载模板失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '下载模板失败'
    ElMessage.error(errorMessage)
  } finally {
    batchLoading.value = false
  }
}

// 导出需求
const handleExportRequirements = async () => {
  try {
    batchLoading.value = true
    
    // 构建导出参数
    const exportParams: any = {}
    
    // 如果有选中的需求，只导出选中的需求
    if (requirementsStore.selectedIds && requirementsStore.selectedIds.length > 0) {
      exportParams.requirement_ids = requirementsStore.selectedIds.join(',')
    } else {
      // 如果没有选中，使用当前筛选条件导出全部
      const filters = requirementsStore.filters
      
      if (filters.search && filters.search.trim()) {
        exportParams.search = filters.search.trim()
      }
      if (filters.project_id && filters.project_id.trim()) {
        exportParams.project_id = filters.project_id.trim()
      }
      if (filters.assignee_id && filters.assignee_id.trim()) {
        exportParams.assignee_id = filters.assignee_id.trim()
      }
      if (filters.reporter_id && filters.reporter_id.trim()) {
        exportParams.reporter_id = filters.reporter_id.trim()
      }
      if (filters.status && filters.status.trim()) {
        exportParams.status = filters.status.trim()
      }
      if (filters.priority) {
        exportParams.priority = filters.priority
      }
      if (filters.requirement_type) {
        exportParams.requirement_type = filters.requirement_type
      }
      if (filters.source) {
        exportParams.source = filters.source
      }
      if (filters.has_version !== undefined) {
        exportParams.has_version = filters.has_version
      }
      if (filters.created_start) {
        exportParams.created_at_start = filters.created_start
      }
      if (filters.created_end) {
        exportParams.created_at_end = filters.created_end
      }
    }
    
    const response = await exportRequirements(exportParams)
    
    // 处理文件下载
    const blob = new Blob([response.data], {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    
    // 从响应头获取文件名，或使用默认文件名
    const contentDisposition = response.headers['content-disposition']
    let filename = `requirements_export_${new Date().getTime()}.xlsx`
    if (contentDisposition) {
      const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
      if (filenameMatch && filenameMatch[1]) {
        filename = filenameMatch[1].replace(/['"]/g, '')
        // 处理中文文件名
        try {
          filename = decodeURIComponent(escape(filename))
        } catch {
          // 如果解码失败，使用原始文件名
        }
      }
    }
    
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    
    // 根据是否有选中显示不同的提示信息
    if (requirementsStore.selectedIds && requirementsStore.selectedIds.length > 0) {
      ElMessage.success(`导出成功：已导出 ${requirementsStore.selectedIds.length} 项选中的需求`)
    } else {
      ElMessage.success('导出成功：已导出全部需求数据')
    }
  } catch (error) {
    console.error('导出需求失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '导出需求失败'
      ElMessage.error(errorMessage)
  } finally {
    batchLoading.value = false
  }
}

// 处理导入文件
const handleImportFile = async (file: any) => {
  try {
    batchLoading.value = true
    
    // 验证文件类型
    const fileType = file.raw.type
    const fileName = file.name
    const validTypes = [
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-excel'
    ]
    
    if (!validTypes.includes(fileType) && !fileName.endsWith('.xlsx') && !fileName.endsWith('.xls')) {
      ElMessage.error('只支持 Excel 文件 (.xlsx, .xls)')
      batchLoading.value = false
    return
  }

    // 确认导入
    await ElMessageBox.confirm(
      `确定要导入文件 "${fileName}" 吗？\n导入前请确保文件格式正确，包含必需的列（标题、项目）。`,
      '确认导入',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
    
    // 调用导入接口
    const response = await importRequirements(file.raw)
    const parsedResponse = ResponseParser.parseResponse(response)
    
    if (parsedResponse.success) {
      const data = parsedResponse.data as any
      const successCount = data?.success_count || 0
      const errorCount = data?.error_count || 0
      const errors = data?.errors || []
      
      let message = `导入完成: 成功 ${successCount} 条`
      if (errorCount > 0) {
        message += `, 失败 ${errorCount} 条`
        
        // 显示错误详情（最多显示前10个）
        const errorPreview = errors.slice(0, 10).join('\n')
        const moreErrors = errors.length > 10 ? `\n... 还有 ${errors.length - 10} 个错误` : ''
        
        ElMessageBox.alert(
          `${message}\n\n错误详情:\n${errorPreview}${moreErrors}`,
          '导入结果',
          {
            confirmButtonText: '确定',
            type: errorCount > 0 ? 'warning' : 'success',
            dangerouslyUseHTMLString: false
          }
        )
      } else {
        ElMessage.success(message)
      }
      
      // 刷新需求列表
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(parsedResponse.message || '导入失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('导入需求失败:', error)
      const errorMessage = ResponseParser.extractMessage(error) || '导入需求失败'
      ElMessage.error(errorMessage)
    }
  } finally {
    batchLoading.value = false
  }
}

const handleClearSelection = () => {
  requirementsStore.clearSelection()
}

const ensureSelection = () => {
  if (!requirementsStore.selectedIds.length) {
    ElMessage.warning('请先选择需求')
      return false
    }
  return true
}

// 批量更新确认处理
const handleBatchUpdateConfirm = async (value: string | { projectId: string; versionId?: string }) => {
  if (!batchUpdateDialogCallback.value) return
  
  batchUpdateLoading.value = true
  try {
    await batchUpdateDialogCallback.value(value)
    batchUpdateDialogVisible.value = false
  } catch (error) {
    console.error('批量更新失败:', error)
  } finally {
    batchUpdateLoading.value = false
  }
}

const handleBatchUpdateStatus = async () => {
  if (!ensureSelection() || !requirementsStore.statusOptions.length) return
  
  // 获取已选择需求的当前状态，如果它们都有相同的状态，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const statuses = selectedRequirements
      .map(req => req.status)
      .filter(status => status) as string[]
    
    // 如果所有已选择的需求都有相同的状态，则使用该状态作为默认值
    if (statuses.length > 0) {
      const uniqueStatuses = [...new Set(statuses)]
      if (uniqueStatuses.length === 1) {
        defaultValue = uniqueStatuses[0]
      }
    }
  }
  
  const options = requirementsStore.statusOptions.map(opt => ({
    value: opt.value,
    label: opt.label
  }))
  
  batchUpdateDialogTitle.value = '批量更新状态'
  batchUpdateDialogPlaceholder.value = '请选择状态'
  batchUpdateDialogType.value = 'select'
  batchUpdateDialogOptions.value = options
  batchUpdateDialogUsers.value = []
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { status: value } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量更新状态成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量更新状态失败')
      }
    } catch (error) {
      console.error('批量更新状态失败', error)
      ElMessage.error('批量更新状态失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchUpdatePriority = async () => {
  if (!ensureSelection() || !requirementsStore.priorityOptions.length) return
  
  // 获取已选择需求的当前优先级，如果它们都有相同的优先级，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const priorities = selectedRequirements
      .map(req => req.priority)
      .filter(priority => priority) as string[]
    
    // 如果所有已选择的需求都有相同的优先级，则使用该优先级作为默认值
    if (priorities.length > 0) {
      const uniquePriorities = [...new Set(priorities)]
      if (uniquePriorities.length === 1) {
        defaultValue = uniquePriorities[0]
      }
    }
  }
  
  const options = requirementsStore.priorityOptions.map(opt => ({
    value: opt.value,
    label: opt.label
  }))
  
  batchUpdateDialogTitle.value = '批量更新优先级'
  batchUpdateDialogPlaceholder.value = '请选择优先级'
  batchUpdateDialogType.value = 'select'
  batchUpdateDialogOptions.value = options
  batchUpdateDialogUsers.value = []
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { priority: value } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量更新优先级成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量更新优先级失败')
      }
    } catch (error) {
      console.error('批量更新优先级失败', error)
      ElMessage.error('批量更新优先级失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchAssign = async () => {
  if (!ensureSelection()) return
  if (!requirementsStore.users.length) {
    ElMessage.warning('暂无可分配用户，请先维护用户列表')
    return
  }
  
  // 获取已选择需求的当前负责人，如果它们都有相同的负责人，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const userIds = selectedRequirements
      .map(req => req.assignee_id)
      .filter(id => id) as string[]
    
    if (userIds.length > 0) {
      const uniqueUserIds = [...new Set(userIds)]
      if (uniqueUserIds.length === 1) {
        defaultValue = uniqueUserIds[0]
      }
    }
  }
  
  batchUpdateDialogTitle.value = '分配负责人'
  batchUpdateDialogPlaceholder.value = '请选择负责人'
  batchUpdateDialogType.value = 'user'
  batchUpdateDialogOptions.value = []
  batchUpdateDialogUsers.value = requirementsStore.users
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { assignee_id: value } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量分配成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量分配失败')
      }
    } catch (error) {
      console.error('批量分配失败', error)
      ElMessage.error('批量分配失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchUpdateType = async () => {
  if (!ensureSelection() || !requirementsStore.typeOptions.length) return
  
  const typeOptions = requirementsStore.typeOptions.map(option => ({
    value: option.value,
    label: option.label || option.value
  }))
  
  // 获取已选择需求的当前类型，如果它们都有相同的类型，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const types = selectedRequirements
      .map(req => req.requirement_type)
      .filter(type => type) as string[]
    
    // 如果所有已选择的需求都有相同的类型，则使用该类型作为默认值
    if (types.length > 0) {
      const uniqueTypes = [...new Set(types)]
      if (uniqueTypes.length === 1) {
        defaultValue = uniqueTypes[0]
      }
    }
  }
  
  batchUpdateDialogTitle.value = '批量更新需求类型'
  batchUpdateDialogPlaceholder.value = '请选择需求类型'
  batchUpdateDialogType.value = 'select'
  batchUpdateDialogOptions.value = typeOptions
  batchUpdateDialogUsers.value = []
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { requirement_type: value as any } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量更新需求类型成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量更新需求类型失败')
      }
    } catch (error) {
      console.error('批量更新需求类型失败', error)
      ElMessage.error('批量更新需求类型失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchUpdateSource = async () => {
  if (!ensureSelection() || !requirementsStore.sourceOptions.length) return
  
  const sourceOptions = requirementsStore.sourceOptions.map(option => ({
    value: option.value,
    label: option.label || option.value
  }))
  
  // 获取已选择需求的当前来源，如果它们都有相同的来源，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const sources = selectedRequirements
      .map(req => req.source)
      .filter(source => source) as string[]
    
    // 如果所有已选择的需求都有相同的来源，则使用该来源作为默认值
    if (sources.length > 0) {
      const uniqueSources = [...new Set(sources)]
      if (uniqueSources.length === 1) {
        defaultValue = uniqueSources[0]
      }
    }
  }
  
  batchUpdateDialogTitle.value = '批量更新需求来源'
  batchUpdateDialogPlaceholder.value = '请选择需求来源'
  batchUpdateDialogType.value = 'select'
  batchUpdateDialogOptions.value = sourceOptions
  batchUpdateDialogUsers.value = []
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { source: value as any } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量更新需求来源成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量更新需求来源失败')
      }
    } catch (error) {
      console.error('批量更新需求来源失败', error)
      ElMessage.error('批量更新需求来源失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchUpdateReporter = async () => {
  if (!ensureSelection()) return
  if (!requirementsStore.users.length) {
    ElMessage.warning('暂无可分配用户，请先维护用户列表')
    return
  }
  
  // 获取已选择需求的当前报告人，如果它们都有相同的报告人，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultValue: string | undefined = undefined
  if (selectedRequirements.length > 0) {
    const userIds = selectedRequirements
      .map(req => req.reporter_id)
      .filter(id => id) as string[]
    
    if (userIds.length > 0) {
      const uniqueUserIds = [...new Set(userIds)]
      if (uniqueUserIds.length === 1) {
        defaultValue = uniqueUserIds[0]
      }
    }
  }
  
  batchUpdateDialogTitle.value = '批量更新报告人'
  batchUpdateDialogPlaceholder.value = '请选择报告人'
  batchUpdateDialogType.value = 'user'
  batchUpdateDialogOptions.value = []
  batchUpdateDialogUsers.value = requirementsStore.users
  batchUpdateDialogDefaultValue.value = defaultValue
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value !== 'string') return
    batchLoading.value = true
    try {
      const payload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { reporter_id: value } as RequirementUpdate
      }
      const response = await batchUpdateRequirements(payload)
      if (response.success) {
        ElMessage.success('批量更新报告人成功')
        requirementsStore.clearSelection()
        await requirementsStore.fetchRequirements()
      } else {
        ElMessage.error(response.message || '批量更新报告人失败')
      }
    } catch (error) {
      console.error('批量更新报告人失败', error)
      ElMessage.error('批量更新报告人失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}


// 加载项目版本列表
const loadProjectVersions = async (projectId: string): Promise<Array<{ value: string; label: string }>> => {
  try {
    const response = await versionAPI.getVersions({
      project_id: projectId,
      page: 1,
      size: 100
    })
    if (response && response.data) {
      // response.data 是 PaginatedResponse<VersionWithStats>，包含 items 属性
      const items = response.data.items || []
      
      return items.map((version: any) => ({
        value: version.id || version._id,
        label: version.name || version.version_number || `版本 ${version.id || version._id}`
      }))
    }
    return []
  } catch (error) {
    console.error('加载版本列表失败:', error)
    return []
  }
}

const handleBatchUpdateProjectAndVersion = async () => {
  if (!ensureSelection()) return
  if (!requirementsStore.projects.length) {
    ElMessage.warning('暂无可选项目，请先维护项目列表')
    return
  }
  
  const projectOptions = requirementsStore.projects.map(project => ({
    value: project.id,
    label: project.name
  }))
  
  // 获取已选择需求的当前项目ID和版本ID，如果它们都有相同的值，则回填
  const selectedRequirements = requirementsStore.requirements.filter(req => 
    requirementsStore.selectedIds.includes(req.id)
  )
  
  let defaultProjectId: string | undefined = undefined
  let defaultVersionId: string | undefined = undefined
  
  if (selectedRequirements.length > 0) {
    const projectIds = selectedRequirements
      .map(req => req.project_id)
      .filter(id => id) as string[]
    
    // 如果所有已选择的需求都有相同的项目ID，则使用该ID作为默认值
    if (projectIds.length > 0) {
      const uniqueProjectIds = [...new Set(projectIds)]
      if (uniqueProjectIds.length === 1) {
        defaultProjectId = uniqueProjectIds[0]
        
        // 如果项目ID相同，尝试获取版本ID
        // 注意：这里需要从版本关联中获取，暂时先不处理
      }
    }
  }
  
  batchUpdateDialogTitle.value = '批量更新项目和版本'
  batchUpdateDialogPlaceholder.value = '请选择'
  batchUpdateDialogType.value = 'project-version'
  batchUpdateDialogOptions.value = []
  batchUpdateDialogUsers.value = []
  batchUpdateDialogProjects.value = projectOptions
  batchUpdateDialogVersions.value = []
  batchUpdateDialogDefaultValue.value = undefined
  batchUpdateDialogDefaultProjectId.value = defaultProjectId
  batchUpdateDialogDefaultVersionId.value = defaultVersionId
  batchUpdateDialogLoadVersions.value = loadProjectVersions
  batchUpdateDialogCallback.value = async (value: string | { projectId: string; versionId?: string }) => {
    if (typeof value === 'string') {
      return
    }
    
    const { projectId, versionId } = value
    
    batchLoading.value = true
    try {
      // 先更新项目ID
      const updatePayload: RequirementBulkUpdate = {
        requirement_ids: requirementsStore.selectedIds.slice(),
        updates: { project_id: projectId } as RequirementUpdate
      }
      const updateResponse = await batchUpdateRequirements(updatePayload)
      
      if (!updateResponse.success) {
        ElMessage.error(updateResponse.message || '批量更新所属项目失败')
        return
      }
      
      // 如果选择了版本，则关联版本
      if (versionId) {
        const requirementIds = requirementsStore.selectedIds.slice()
        const results = await Promise.allSettled(
          requirementIds.map(requirementId =>
            versionAPI.addRequirementToVersion(versionId, {
              requirement_id: requirementId,
              relation_type: RelationType.INCLUDED
            })
          )
        )
        
        // 统计成功和失败的数量
        const successCount = results.filter(r => r.status === 'fulfilled' && r.value.success).length
        const failCount = results.length - successCount
        
        if (successCount > 0) {
          ElMessage.success(`批量更新项目和版本成功：${successCount} 项需求已更新`)
        }
        
        if (failCount > 0) {
          ElMessage.warning(`${failCount} 项需求版本关联失败，可能已关联或不存在`)
        }
      } else {
        ElMessage.success('批量更新所属项目成功')
      }
      
      requirementsStore.clearSelection()
      await requirementsStore.fetchRequirements()
    } catch (error) {
      console.error('批量更新项目和版本失败', error)
      ElMessage.error('批量更新项目和版本失败，请稍后重试')
      throw error
    } finally {
      batchLoading.value = false
    }
  }
  
  batchUpdateDialogVisible.value = true
}

const handleBatchDelete = async () => {
  if (!ensureSelection()) return
  try {
    await ElMessageBox.confirm(
      `即将删除 ${requirementsStore.selectedIds.length} 条需求，删除后无法恢复，是否继续？`,
      '批量删除确认',
      {
        type: 'warning',
        confirmButtonText: '删除',
        cancelButtonText: '取消'
      }
    )
  } catch {
    return
  }

  batchLoading.value = true
  try {
    const response = await batchDeleteRequirements(requirementsStore.selectedIds.slice())
    if (response.success) {
      ElMessage.success('批量删除成功')
      requirementsStore.clearSelection()
      await requirementsStore.fetchRequirements()
    } else {
      ElMessage.error(response.message || '批量删除失败')
    }
  } catch (error) {
    console.error('批量删除失败', error)
    ElMessage.error('批量删除失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}
</script>

<style scoped>
.requirements-workspace {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 24px;
  background: #f4f6fb;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.workspace-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 24px;
  border-radius: 16px;
  background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);
  box-shadow: 0 12px 32px rgba(36, 61, 99, 0.08);
  flex-shrink: 0;
}

.header-left .title-block h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: #1f2a44;
}

.header-left .subtitle {
  margin: 6px 0 0;
  font-size: 14px;
  color: #607089;
}

.header-left {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}

.support-actions {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.support-button {
  font-size: 13px;
  color: #4460a4;
  padding: 6px 12px;
  border-radius: 12px;
}

.support-button :deep(.el-icon) {
  font-size: 14px;
}

.support-button:hover {
  background: rgba(64, 158, 255, 0.12);
  color: #2563eb;
}

.support-upload {
  display: inline-flex;
}

.support-upload :deep(.el-upload) {
  display: inline-flex;
}

.header-right {
  display: flex;
  gap: 12px;
  align-items: center;
}

.project-selector-wrapper {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: 8px;
}

.project-label {
  font-size: 14px;
  color: #606266;
  font-weight: 500;
  white-space: nowrap;
}

.project-selector {
  min-width: 180px;
}

.view-switcher {
  background: #eef3ff;
  border-radius: 12px;
}

.refresh-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.create-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.workspace-main {
  margin-top: 0;
  display: flex;
  gap: 16px;
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  height: 100%;
}

.filter-panel {
  width: 300px;
  position: relative;
  transition: width 0.24s ease, transform 0.24s ease;
  flex-shrink: 0;
  max-width: 400px; /* 限制筛选面板最大宽度 */
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

.filter-panel.is-collapsed {
  width: 60px;
  transform: translateX(-12px);
}

.filter-panel.is-collapsed .filter-body {
  display: none;
}

.filter-panel.is-collapsed .filter-header {
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 8px;
}

.filter-panel.is-collapsed .filter-header h3 {
  writing-mode: vertical-rl;
  margin: 0;
  letter-spacing: 4px;
}

.filter-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 24px rgba(33, 51, 96, 0.06);
  margin-bottom: 12px;
  flex-shrink: 0;
}

.filter-header h3 {
  margin: 0;
  font-size: 15px;
  color: #2b3c5c;
  font-weight: 600;
}

.collapse-btn {
  color: #4b5e89;
}

.filter-body {
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 24px rgba(33, 51, 96, 0.06);
  padding: 16px 18px;
  overflow-y: auto;
  overflow-x: hidden;
  flex: 1;
  min-height: 0;
  max-height: 100%;
  
  &::-webkit-scrollbar {
    width: 6px;
  }
  
  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;
    
    &:hover {
      background: #a8a8a8;
    }
  }
  
  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
  }
}

.workspace-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.workspace-body {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.fade-slide-enter-active,
.fade-slide-leave-active {
  transition: all 0.28s ease;
}

.fade-slide-enter-from,
.fade-slide-leave-to {
  opacity: 0;
  transform: translateY(12px) scale(0.99);
}

.prompt-select-wrapper {
  padding-top: 8px;
  
  .select-hint {
    font-size: 13px;
    color: #909399;
    margin-bottom: 16px;
    padding: 8px 12px;
    background: #f0f9ff;
    border-left: 3px solid #409eff;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    
    &::before {
      content: '';
      display: inline-block;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: #409eff;
    }
  }
  
  .select-label {
    font-size: 14px;
    color: #606266;
    margin-bottom: 12px;
    font-weight: 500;
  }
  
  :deep(.el-select) {
    .el-input__inner {
      height: 40px;
      line-height: 40px;
      font-size: 14px;
      border-radius: 6px;
      border-color: #dcdfe6;
      transition: all 0.2s;
      
      &:hover {
        border-color: #c0c4cc;
      }
      
      &:focus {
        border-color: #409eff;
      }
    }
    
    .el-input__suffix {
      .el-select__caret {
        color: #909399;
        font-size: 14px;
      }
    }
  }
  
  :deep(.el-select-dropdown) {
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    
    .el-select-dropdown__item {
      height: 36px;
      line-height: 36px;
      padding: 0 16px;
      font-size: 14px;
      transition: all 0.2s;
      
      &:hover {
        background-color: #f5f7fa;
        color: #409eff;
      }
      
      &.selected {
        color: #409eff;
        font-weight: 500;
        background-color: #ecf5ff;
      }
    }
  }
}
</style>

<style>
/* 批量操作弹窗全局样式 */
.batch-operation-dialog {
  border-radius: 12px;
  overflow: hidden;
  width: 480px;
}

.batch-operation-dialog .el-message-box__header {
  padding: 20px 24px 16px;
  border-bottom: 1px solid #ebeef5;
  background: linear-gradient(135deg, #f8fbff 0%, #ffffff 100%);
}

.batch-operation-dialog .el-message-box__title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  line-height: 1.4;
}

.batch-operation-dialog .el-message-box__headerbtn {
  top: 20px;
  right: 20px;
}

.batch-operation-dialog .el-message-box__headerbtn .el-message-box__close {
  color: #909399;
  font-size: 18px;
}

.batch-operation-dialog .el-message-box__headerbtn .el-message-box__close:hover {
  color: #606266;
}

.batch-operation-dialog .el-message-box__content {
  padding: 24px;
  background: #ffffff;
}

.batch-operation-dialog .el-message-box__message {
  margin: 0;
  padding: 0;
}

.batch-operation-dialog .el-message-box__btns {
  padding: 16px 24px;
  border-top: 1px solid #ebeef5;
  background: #fafbfc;
}

.batch-operation-dialog .el-message-box__btns .el-button {
  padding: 10px 20px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s;
}

.batch-operation-dialog .el-message-box__btns .el-button--default {
  border-color: #dcdfe6;
  color: #606266;
  background: #ffffff;
}

.batch-operation-dialog .el-message-box__btns .el-button--default:hover {
  color: #409eff;
  border-color: #c6e2ff;
  background: #ecf5ff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary {
  background: #409eff;
  border-color: #409eff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary:hover {
  background: #66b1ff;
  border-color: #66b1ff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary:active {
  background: #3a8ee6;
  border-color: #3a8ee6;
}
</style>

